package multidraw.model;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.Vector;

public class LineShape extends TwoEndShape implements TwoEndBoundaryShape {
	Point p1;
	Point p2;

	public LineShape(Point p1, Point p2, Color c, long id) {
		this.p1 = p1;
		this.p2 = p2;
		this.penColor = c;
		this.shapeID = id;
	}

	public void draw(Graphics g, boolean selected) {
		Graphics2D g2 = (Graphics2D) g;
		
		Color c = g2.getColor();

		g2.setColor(penColor);

		if (!selected) {
			g2.drawLine(p1.x, p1.y, p2.x, p2.y);
		} else {
			// highlight the object, draw with dashes line			
			Stroke oldStroke = g2.getStroke();

			System.out.println("Chaning stroke ...");
			g2.setStroke(dashed);

			g2.drawLine(p1.x, p1.y, p2.x, p2.y);

			// set back the old stroke
			g2.setStroke(oldStroke);
		}
		
		g2.setColor(c);
	}
	
	public void drawOutline(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;

	    // highlight the object, draw with dashes line
		

		Stroke oldStroke = g2.getStroke();

		System.out.println("Changing stroke ...");
		g2.setStroke(dashed);

		g2.drawLine(p1.x, p1.y, p2.x, p2.y);

		// set back the old stroke
		g2.setStroke(oldStroke);
		
	}
	
	public boolean isInsideSelectionalArea(int X, int Y) {
		//compute the distance to the line
		//then if the distance is small than eps, then mark it as selected
		
		double d;
		if (p1.x == p2.x) {
			System.out.println("Case 1: vertical line");
			d = Math.abs(X - p1.x);
		}
		else {
			System.out.println("Case 2: non vertical line");
			double k = (p2.getY() - p1.getY())/(p2.getX() - p1.getX());
			double a = k;
			double b = -1;
			double c = p1.getY() - k * p1.getX();
			
			
			System.out.println("p1 = " + p1);
			System.out.println("p2 = " + p2);
			System.out.println("x,y = " + X + ", " + Y);
			
			System.out.println("k" + k);
			System.out.println("b" + b);
			System.out.println("c" + c);
			System.out.println(Math.abs(a * X + b * Y + c));
			d = Math.abs(a * X + b * Y + c)/Math.sqrt(a * a + b * b);			
		}
		
		System.out.println("distance = " + d);
		
		if (d <= DISTANCE_EPS 
				&& (X >= Math.min(p1.x, p2.x)) 
				&& (X <= Math.max(p1.x, p2.x))) return true;
		return false;
	}
	
	public void updateShapeInfo(Point p1, Point p2) {
		//construct the rectangle from the points
		this.p1 = p1;
		this.p2 = p2;
	}
	
	public boolean isInsideBoundaryRectangle(Point p) {
		return isInsideSelectionalArea(p.x, p.y);
	}
	
	public Shape getOutlineShape() {
		return new LineShape((Point)p1.clone(), (Point)p2.clone(), penColor, -1);
	}
	
	public void translate(Point p1, Point p2) {
		this.p1.translate(p2.x - p1.x, p2.y - p1.y);
		this.p2.translate(p2.x - p1.x, p2.y - p1.y);
	}
	
	/**
	 * Get control points list: points at 4 corners, clock-wise, starting from leftX, topY
	 * @return
	 */
	protected Vector<Point> getControlPoints() {
		Vector<Point> cl = new Vector<Point>(2, 1);
						
		cl.add(p1);
		cl.add(p2);		
		return cl;
	}
	
	public ControlPair getControlPoints(Point p) {
		Vector<Point> controlPointList = getControlPoints();
		for (int i = 0; i < controlPointList.size(); i++) {
			if (p.distance(controlPointList.get(i)) < DISTANCE_EPS ) {
				ControlPair cp = new ControlPair(controlPointList.get((i + 1 ) % 2), controlPointList.get(i));
				return cp;
			}
		}
		
		return null;
	}
}
